.SYN COMPILE
.FIELD VALUE 0 TYPE 3 ;
.CONSTANT NAME 1 FIELD 3 CONSTANT 2
		FUNC 4  UNDEFINED 0 AVAILFIELDS 5 ;
.NAME NUMBER '0' ID '0' SAVEID '2' TEMP 'Z' STACK 'Y' UNSTACK '!' ;
.FUNCTION IDNAME EXPRESSION TERM FACTOR
	CONSTSIMP CONSTEXP CONSTTERM CONSTFAC
	IDCONS ERRORMESSAGE CFAC CEXP IDNEW
	CATNAME IDFIELD CHECKFRANGE PHRASE
	;
RVALUE =
	IDNAME &CATNAME (':' IDFIELD .CAT ('M' ID:VALUE)
	/ .EMP )
	/CONSTSIMP
		.CAT('N/' UNSTACK ' ')
	/ '+' EXPRESSION .CAT('!')
	;
EXPRESSION = TERM $( '+'TERM .OUT('!+')
		/'-' TERM .OUT('!-')
	)
	;
TERM = FACTOR
	$('*' FACTOR .OUT('!*')
	/'/''256' .OUT('HZ')
	.OUT('!D')
	.OUT('ZY')
	/'%256'
	.OUT('HY')
	.OUT('N/''256*')
	.OUT('!-')
	)
	;
FACTOR='(' EXPRESSION ')'
	/CONSTSIMP .OUT('N/' UNSTACK 'Y')
	/IDNAME &CATNAME (':' IDFIELD
		.CAT('M'ID:VALUE)
		/.EMP) .OUT('Y')
	/'-'FACTOR .OUT('!Z')
		.OUT('N/''0Y')
		.OUT('Z-')
	;
CATNAME = ID:VALUE=:STACK
	.ACT('!L')	!ACTS AS A ONE BYTE MACRO
	;
TOPLACE = IDNAME ID=:SAVEID
	(':' IDFIELD .CAT( 'I'  ID:VALUE)
	/.EMP )
		SAVEID=:ID &CATNAME
	;
DECLARE = '.FIELD' $ (IDNEW ID=:SAVEID
	CONSTEXP  &CHECKFRANGE NUMBER=:SAVEID:VALUE
		FIELD=:SAVEID:TYPE
		)	';'
	/'.NAME' $ ( IDNEW ID=:SAVEID
		CONSTEXP
		UNSTACK=:SAVEID:VALUE
		NAME=:SAVEID:TYPE
	)		';'
	/ '.CONSTANT' $ (IDNEW ID=:SAVEID
		CONSTEXP
		CONSTANT=:SAVEID:TYPE
		UNSTACK=:SAVEID:VALUE
	)		';'
	/'.FUNCTION' $ (IDNEW FUNC=:ID:TYPE)
	';'
	;
CONSTEXP = CONSTTERM $( '+' CONSTTERM .ACT('!+')
	/'-' CONSTTERM .ACT('!-')
	)
	;
CONSTTERM = CONSTFAC $( '*' CONSTFAC .ACT ('!*')
	)
	;
CONSTSIMP = .NUM NUMBER=:STACK
	/IDCONS ID:VALUE=:STACK
	/.STR "'" .ACT ('N/0SY')	!VALUE IS FIRST CHARACTER
	/'.X' .HEXNUM ]NUMBER
	;
CONSTFAC =
	CONSTSIMP
	/'-' CONSTFAC .ACT('!Z' 'N/0Y' 'Z-')
	/'(' CONSTEXP ')'
	;
IDTYPE = .ACT ('LI'	!IS IT AN ID?
		'F/' *1 !NO, RETURN
		'ME'	!DEFINE OR FIND
		'0M3Y' 'Z='	!ID TYPE==TEMP?
		'L' 'R'	!TAKE AND RETURN
		'.' *1	!NOW ACCEPT OR REWIND INPUT
		'L'  'Z9' )
	;
IDNAME = .PREP NAME=:TEMP IDTYPE
	;
IDFIELD = .PREP FIELD=:TEMP IDTYPE
	;
IDFUNC = .PREP FUNC =: TEMP IDTYPE
	;
IDCONS = .PREP CONSTANT=:TEMP IDTYPE
	;
IDNEW = .PREP UNDEFINED=:TEMP IDTYPE
	;
CHECKFRANGE = .IF( NUMBER<=AVAILFIELDS)
	.RETURN
	.ELSE
		.ERMS( NUMBER ' IS TOO BIG FOR A FIELD')
	.END
	;
AOUT = '*1' .OUT('U')
	/ '*2' .OUT ( 'V' )
	/ '*' .OUT ( 'C' )
	/( .STR "'"/.STR'"') .OUT ( 'P' * )
	/RVALUE .OUT('C')
	/'.H' RVALUE .OUT('H')
	/'.' .OUT('XN')
	;
NOTSYN = ( '.OUT' '(' $ AOUT ')'
	/ '.LAB'  .OUT ( 'P... ') AOUT
	)
	.OUT ( 'O' )
	/ '.ACT' '(' $(
		( .STR "'" / .STR '"' ) .ACT ('C')
			('*1' .ACT('U')
			/'*2' .ACT ('V')
			/.EMP)
			.ACT('O')
		/ .STR '!'
		) ')'
	/']' RVALUE .OUT('Y')
	/ RVALUE '=:' TOPLACE .OUT()
	/'.IF' '(' CEXP ')' .OUT('F/' *1) $ NOTSYN
		('.ELSE' .OUT ('J/'*2)  .LAB*1 .OUT('S')  $NOTSYN '.END' .LAB*2
		/'.END'	.LAB*1 .OUT('S')  )
	/'.CAT'
		'(' $AOUT ')'
	/'.CONDLAB'
		('*1' .OUT ('UY')
		.OUT ('0=')
		.OUT ('T/' *1)
		.OUT ('P... ')
		.OUT ('U')
	/'*2' .OUT('VY')
		.OUT('0=')
		.OUT('T/' *1)
		.OUT('P... ')
		.OUT('V')
	)
	.OUT('O')
	.OUT('S')	!!! NOTE SIDE EFFECT !!!
	.LAB *1
	/ERRORMESSAGE
	/'.ERROR' .OUT('SF')
	/'.SUCCEED' .OUT('S')
	/'.FAIL' .OUT('SF')
	/ '&' IDFUNC .OUT ( 'G' * )
	/'.RETURN' .OUT ( 'R' )
	/.STR '!'
	/'.WHILE' .LAB *1
		'(' CEXP ')' .OUT ('F/' *2)
		$NOTSYN
		'.ENDWHILE'
			.OUT('J/' *1)
			.LAB *2
	;
CRIGHT=
	'==' .OUT ('Y')
	RVALUE .OUT('=')
	/'!=' .OUT('Y')
	RVALUE .OUT('=') .OUT ('SC')
	/'<=' .OUT('Y')
	RVALUE .OUT('<') .OUT ('SC')
	/'>=' .OUT('Y')
	RVALUE .OUT('>') .OUT('SC')
	/'<' .OUT('Y')
	RVALUE .OUT('>')
	/'>' .OUT ('Y')
	RVALUE .OUT('<')
	;
CTERM = CFAC $( '.ANDIF' .OUT('F/' *2) CFAC)
	.CONDLAB *2
	;
CFAC = RVALUE CRIGHT
	/'.NOT' CFAC .OUT('SC')
	/'(' CEXP ')'
	/'&' IDNEW .OUT('G' *)
	;
CEXP = CTERM $( '.ORIF' .OUT('T/' *1) CTERM)
	.CONDLAB *1
	;
ERRORMESSAGE = '.ERMS' '(' .OUT('T/'*1) $AOUT
	')' .OUT('XO') .LAB *1


	;
SYN = (  IDNEW .OUT ('G' *)
	/ .STR "'"  .OUT ( 'LM'  * ) .OUT ( 'L' )
	/'.ID'  .OUT ( 'LI' )
		.OUT ( 'F/' *1 ) .OUT ( 'L' ) .OUT ( 'ME' ) .LAB *1
	/'.NUM' .OUT ( 'LN' ) .OUT ( 'L' )
	/'.STR' (.STR "'" / .STR '"' ) .OUT ( 'LQ' * ) .OUT ( 'L' )
	/'.EMP' .OUT ( 'S' )
	/'$'	.LAB *1 SYN .OUT('T/' *1) .OUT('S')
	/'(' PHRASE ')'
	/'.HEXNUM' .OUT('LH') .OUT('L')
	)
	(ERRORMESSAGE
	/.EMP)


	;
SEQ = SYN .OUT ('F/' *1)
	$ ( SYN .OUT ( 'X' ) / NOTSYN )
	.LAB *1
	;
ALTS = SEQ $('/' .OUT ('T/'*1) SEQ)
	.CONDLAB *1
	;
PHRASE = '.PREP' $NOTSYN ALTS
	/ALTS
	/NOTSYN $NOTSYN

	;
STATEMENT = .ID .LAB * '=' PHRASE ';' .OUT ( 'R' )
	(.STR '!' /.EMP)

	;
COMPILE = '.SYN'  .ID  .OUT('S')
	.OUT ( 'XM;' ) .OUT ('G' *) .OUT('E')
	.ACT('XM;') $ DECLARE   $ STATEMENT
	;
